public class Robinson implements Cloneable{
    /**
     * 游戏主人公鲁滨逊的类
     *
     * @param age               鲁滨逊的年龄，取值范围为[5,60]
     * @param intelligence      鲁滨逊的智力，取值范围为[70,120]
     * @param strength          鲁滨逊的体力，取值范围为[0,100]
     * @param mood              鲁滨逊的心情，标志他的精神状况，取值范围为[0,100]
     *
     * @param flag              鲁滨逊在一年里已经选择过活动的次数，每新一年更新为0
     * @param sailing_time      鲁滨逊总共航海的次数
     * @param woodworking_time  鲁滨逊总共做木工的次数
     * @param crops_amount      鲁滨逊上岛后所拥有的谷物量
     * @param sheep_amount      鲁滨逊上岛后所拥有的羊羊数量
     *
     * @param date_on_island    鲁滨逊漂流上岛时的年龄
     * @param alert             鲁滨逊的警惕性，针对荒岛上赶走野人的剧情而设置
     * @param index             该鲁滨逊对应的存档编号
     * @param gotFriday         标记鲁滨逊是否救下了星期五，默认为false
     * @param save_father       标记鲁滨逊是否救下了星期五的父亲，默认为false
     * @param live              标记鲁滨逊是否存活，默认为true
     * @param rescued           标记鲁滨逊是否获救，默认为false
     * @param background        记录玩家当前的背景
     * @param time              记录鲁滨逊被存档的时间
     *
     * @param S_INCREASE        鲁滨逊每次吃饭后所增加的体力
     * @param S_MAX             鲁滨逊体力的最大值
     */
    private int age = 5;
    private double intelligence = 70;    //90  70  80
    private double strength = 20;
    private double mood = 70;

    int flag = 0;
    int sailing_time = 0;  //
    private int woodworking_time = 0;
    private double crops_amount = 0;
    private double sheep_amount = 0;

    private int date_on_island = 0;
    private boolean alert = false;
    private int index = 0;
    boolean gotFriday = false;
    boolean save_father = false;
    boolean live = true;
    boolean rescued = false;

    String background = "";
    String time;
    String way_of_death = "";

    private static final int A_MIN = 5;
    public static final int A_MAX = 60;
    private static final int I_INCREASE = 10;
    private static final int I_DECREASE = 10;
    private static final int I_MIN = 70;
    private static final int I_MAX = 120;
    private static final int S_INCREASE = 10;
    private static final int S_DECREASE = 10;
    public static final int S_MIN = 1;
    public static final int S_MAX = 100;
    private static final int M_INCREASE = 10;
    private static final int M_DECREASE = 10;
    private static final int M_MIN = 1;
    public static final int M_MAX = 100;
    private static final int TRIGGER_WOOD_SHIP = 15;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getIntelligence() {
        return intelligence;
    }
    /**
     * 增减鲁滨逊智力值的类
     *
     * @param amount    需要增减的数值，正数为增，负数为减
     */
    public void setIntelligence(double amount) {
        if (intelligence + amount > I_MAX) {
            intelligence = I_MAX;
        }
        else if (intelligence + amount < I_MIN) {
            intelligence = I_MIN;
        }
        else {
            intelligence += amount;
        }
    }

    public double getStrength() {
        return strength;
    }
    /**
     * 增减鲁滨逊体力值的类
     *
     * @param amount    需要增减的数值，正数为增，负数为减
     */
    public void setStrength(double amount) {
        if (strength + amount > S_MAX) {
            strength = S_MAX;
        }
        else if (strength + amount < S_MIN) {
            strength = S_MIN;
        }
        else {
            strength += amount;
        }
    }

    public double getMood() {
        return mood;
    }
    /**
     * 增减鲁滨逊心情值的类
     *
     * @param amount    需要增减的数值，正数为增，负数为减
     */
    public void setMood(double amount) {
        if (mood + amount > M_MAX) {
            mood = M_MAX;
        }
        else if (mood + amount < M_MIN) {
            mood = M_MIN;
        }
        else {
            mood += amount;
        }
    }

    public int getDate_on_island() {
        return date_on_island;
    }

    public void setDate_on_island(int date_on_island) {
        if (this.date_on_island == 0 && date_on_island >= Settings.FIRST_SALES)   // 上岛时间只能更改一次，且取值应大于等于首次出海时鲁滨逊的年龄
            this.date_on_island = date_on_island;
    }

    public boolean isAlert() {
        return alert;
    }
    /**
     * 设置鲁滨逊是否对野人有了警惕心，只会设置为true
     */
    public void setAlert() {
        this.alert = true;
    }

    public void setAlert(boolean alert) {
        this.alert = alert;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    public int getSailing_time() {
        return sailing_time;
    }

    public void setSailing_time(int sailing_time) {
        this.sailing_time = sailing_time;
    }

    public boolean isGotFriday() {
        return gotFriday;
    }

    public void setGotFriday(boolean gotFriday) {
        this.gotFriday = gotFriday;
    }

    public boolean isRescued() {
        return rescued;
    }

    public void setRescued(boolean rescued) {
        this.rescued = rescued;
    }

    public int getWoodworking_time() {
        return woodworking_time;
    }

    public void setWoodworking_time(int woodworking_time) {
        this.woodworking_time = woodworking_time;
    }

    public double getCrops_amount() {
        return crops_amount;
    }

    public void setCrops_amount(double crops_amount) {
        this.crops_amount = crops_amount;
    }

    public double getSheep_amount() {
        return sheep_amount;
    }

    public void setSheep_amount(double sheep_amount) {
        this.sheep_amount = sheep_amount;
    }

    public String getBackground() {
        return background;
    }

    public void setBackground(String background) {
        this.background = background;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public void setLive(boolean live) {
        this.live = live;
    }

    /**
     * 按年龄更新鲁滨逊的体力，在20岁之前体力按一定函数增长，在40岁之后体力按一定函数降低
     * 若年龄超出了年龄上限，则自动死亡
     */
    void updateHealth(int flag, int times){
        if (flag == times) { // 若玩家已经完成了times次选择（即过完一年），则鲁滨逊的年龄+1,按年更新更新体力值
            age ++;
            if (age < 20 - 1) {     // 为了防止除数为0或者1
                setStrength((S_MAX - strength)/(20 - age));
            }
            else if (age > 40) {
                setStrength(-((strength - S_MIN)/(A_MAX + 1 - age)));   // 为了防止除数为0或者1
            }
        }
        if (age >= A_MAX || strength < S_MIN || mood < M_MIN) { // 每次玩家选择完一项活动后都要检查
            live = false;
        }
    }
    /**
     * 检查鲁滨逊的身体健康的方法，若体力/心情过低，会导致人物的死亡
     *
     * @return 布尔值，表征鲁滨逊能否活到下一年
     */
    public boolean isLive(){
        return live;
    }
    /**
     * 鲁滨逊的日常活动之吃饭，吃饭可以增加一定的体力
     *
     */
    void eat(){
        setStrength(S_INCREASE / 3.0);
    }
    /**
     * 鲁滨逊的日常活动之玩耍，玩耍可以增加一定的体力、智力和心情
     *
     */
    void play(){
        setStrength(S_INCREASE / 2.0);
        setIntelligence(I_INCREASE / 10.0);
        setMood(M_INCREASE);
    }
    /**
     * 鲁滨逊的日常活动之读书，读书可以增加一定的智力
     *
     */
    void read(){
        setIntelligence(I_INCREASE);
    }
    /**
     * 鲁滨逊的日常活动之航海，航海可以增加一定的体力、智力和心情
     * 累加航海次数，当开始第四次航海时，触发流落荒岛情节
     *
     */
    void sail(){
        sailing_time ++;
        setStrength(S_INCREASE);
        setIntelligence(I_INCREASE / 2.0);
        setMood(M_INCREASE);
    }
    /**
     * 鲁滨逊的荒岛日常活动之做木工，做木工会减少一定的体力
     * 累加做木工次数，当累计到15次时，触发造出大船但无法出海的剧情/造出小船开启海上求援支线
     * 扩展点：1.做木工可以分为做家具/造船两种，分别计次
     *        2.当做了一次家具之后，可以解锁新的活动：（在家具上）休息
     *
     * @param friday 辅助角色，在参与工作时可以增加鲁滨逊的效率
     */
    void woodwork(Friday friday){
        woodworking_time ++;
        if (woodworking_time == TRIGGER_WOOD_SHIP) {
            double r = Math.random();
            if (r < 1.0 / 3.0) { // 1/3的概率造出大船
                // 返回 给用户相应 的剧情
                setMood(-((mood - M_MIN)/M_DECREASE));  // 心情变差
                woodworking_time = 0; // 从头再来
            }
            else if (r > 7.0 / 8.0) { // 1/8的概率造出小船，可以出海
                mood = M_MAX;   // 心情极好
                // 出海求援，时间忽略不计
                // 扩展点 做成小游戏
                boolean success = Math.random() > 0.95;
                if (success) {
                    // 输出成功获救信息
                    rescued = true;
                    return;
                }
            }
        }
        setStrength(-S_DECREASE);
    }
    /**
     * 鲁滨逊的荒岛日常活动之种地
     * 种地成功->心情会变好
     * 种地失败->心情变差;星期五服从度减低
     * 智力越高，越容易种出粮食
     * 粮食增长呈指数,如果有星期五的参与，会更多
     *
     * 扩展点： 种地次数越多越容易种出粮食；
     *         种地会减少体力；
     *         页面上出现很多农作物/显示农作物存储量（？
     *
     * @param friday 辅助角色，在参与工作时可以增加鲁滨逊的效率
     */
    void cultivate(Friday friday){
        // 种地的材料从本来所拥有的谷物量里出
        double seeds = (crops_amount > 100) ? 100 : (crops_amount / 10.0);
        // 计算种地成功率
        boolean success = Math.random() * 50 < intelligence - 70;

        if (success) {
            setMood(M_INCREASE / 3.0);
            friday.setObedience(5 * Math.random());
            crops_amount += seeds * 80 *(1 + 0.05 * friday.is_work.get(this.flag) * (friday.getObedience() / 1000)); // 春种一粒粟 秋收万颗子
        }
        else {
            setMood(-(M_INCREASE / 3.0));
            friday.setObedience(-5 * Math.random());
        }
    }
    /**
     * 鲁滨逊的荒岛日常活动之养羊
     * 养羊成功->心情会变好，羊羊++
     * 智力越高，越容易成功;不成功则星期五服从度减低
     * 羊群数量增长呈线性,如果有星期五的参与，会更多
     *
     * 扩展点： 种地次数越多越容易种出粮食；
     *         种地会减少体力；
     *         页面上出现很多羊羊
     *
     * @param friday 辅助角色，在参与工作时可以增加鲁滨逊的效率
     */
    void sheep(Friday friday){
        // 计算成功率
        boolean success = Math.random() * 50 < intelligence - 70;

        if (success) {
            setMood(M_INCREASE / 3.0);
            friday.setObedience(5 * Math.random());
            sheep_amount += 10.0 *(1 + 0.1 * friday.is_work.get(this.flag) * (friday.getObedience() / 1000));
        }
        else {
            setMood(-(M_INCREASE / 3.0));
            friday.setObedience(-5 * Math.random());
        }
    }
    /**
     * 鲁滨逊的荒岛日常活动之遛弯,心情会变好,体力增加;如果有星期五的参与,心情会更好
     *
     * @param friday 辅助角色，在参与工作时可以增加鲁滨逊的效率
     */
    void hangout(Friday friday){
        setMood((M_INCREASE / 3.0)*(1 + 0.1 * friday.is_work.get(this.flag) * (friday.getObedience() / 1000)));
        setStrength(S_INCREASE / 5.0);
    }

    public Robinson(){}

    /**
     * 复制一个robinson.
     * @param robinson 被复制的robinson对象
     */

    public Robinson(Robinson robinson){
        this.age = robinson.getAge();
        this.flag = robinson.getFlag();
        this.alert = robinson.isAlert();
        this.date_on_island = robinson.getDate_on_island();
        this.index = robinson.getIndex();
        this.crops_amount = robinson.getCrops_amount();
        this.gotFriday = robinson.isGotFriday();
        this.intelligence = robinson.getIntelligence();
        this.mood = robinson.getMood();
        this.rescued = robinson.isRescued();
        this.sailing_time = robinson.getSailing_time();
        this.sheep_amount = robinson.getSheep_amount();
        this.live = robinson.isLive();
        this.rescued = robinson.isRescued();
        this.strength = robinson.getStrength();
        this.woodworking_time = robinson.getWoodworking_time();
        this.background = robinson.getBackground();
    }
}
